#include <cassert>
#include <ctime>

#include "MessageDispatcher.h"
#include "Message.h"
#include "Entity/BaseEntity.h"
#include "Entity/EntityManager.h"


void MessageDispatcher::DeliverMessage(BaseEntity* entity, const Message& msg)
{
	assert( entity->HandleMessage(msg) && "<MessageDispatcher::ProcessMessage>: Failed to Process Message" );
}


MessageDispatcher& MessageDispatcher::GetInstance()
{
	static MessageDispatcher instance;
	
	return instance;
}

void MessageDispatcher::DispatchMessage(double delay, AITypes::EntityID sender,
	AITypes::EntityID receiver, AITypes::MessageType msg, void* extraInfo)
{
	EntityManager& entityMgr = EntityManager::GetInstance();

	BaseEntity* entitySender = entityMgr.GetEntityFromID(sender);
	assert(entitySender && "<MessageDispatcher::DispatchMessage>: Invalid Sender ID");

	BaseEntity* entityReceiver = entityMgr.GetEntityFromID(receiver);
	assert(entityReceiver && "<MessageDispatcher::DispatchMessage>: Invalid Receiver ID");

	if (entitySender && entityReceiver)
	{
		Message message(sender, receiver, msg, delay, extraInfo);

		if (delay > 0.0f)
		{
			const clock_t t = clock();
			message.m_delay += t;
			m_messageQueue.insert(message);
		}
		else
		{
			DeliverMessage(entityReceiver, message);
		}
	}
}

void MessageDispatcher::DispatchDelayedMessages()
{
	const clock_t t = clock();
	assert(t > -1 && "<MessageDispatcher::DispatchDelayedMessages>:Inavlid Clock Time");

	if (t > -1)
	{
		for (MessageQueue::const_iterator it = m_messageQueue.begin();
			it != m_messageQueue.end(); ++it)
		{
			const Message &msg = *it;

			if (msg.m_delay < t)
			{
				EntityManager& entityMgr = EntityManager::GetInstance();

				BaseEntity* entity = entityMgr.GetEntityFromID(msg.m_receiver);

				assert(entity && "<MessageDispatcher::DispatchDelayedMessages>:: Invalid receiver on message");

				if (entity)
				{
					DeliverMessage(entity, msg);
				}
			}
			else
			{
				break;
			}
		}
	}
}